D:\a\tools.proto\tools.proto\compiler\src\compiler\structure.rs
Line | Count | Source |
1 | | // Copyright (c) 2024, BlockProject 3D |
2 | | // |
3 | | // All rights reserved. |
4 | | // |
5 | | // Redistribution and use in source and binary forms, with or without modification, |
6 | | // are permitted provided that the following conditions are met: |
7 | | // |
8 | | // * Redistributions of source code must retain the above copyright notice, |
9 | | // this list of conditions and the following disclaimer. |
10 | | // * Redistributions in binary form must reproduce the above copyright notice, |
11 | | // this list of conditions and the following disclaimer in the documentation |
12 | | // and/or other materials provided with the distribution. |
13 | | // * Neither the name of BlockProject 3D nor the names of its contributors |
14 | | // may be used to endorse or promote products derived from this software |
15 | | // without specific prior written permission. |
16 | | // |
17 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
18 | | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
19 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
20 | | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
21 | | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
22 | | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
23 | | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
24 | | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
25 | | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
26 | | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
27 | | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | |
29 | | use std::cell::Cell; |
30 | | use crate::compiler::error::Error; |
31 | | use crate::compiler::r#enum::Enum; |
32 | | use crate::compiler::util::store::name_index; |
33 | | use crate::compiler::util::try2; |
34 | | use crate::compiler::util::types::Name; |
35 | | use crate::compiler::Protocol; |
36 | | use crate::model::protocol::{Description, Endianness}; |
37 | | use crate::model::structure::{SimpleType, StructFieldRaw, StructFieldView}; |
38 | | use bp3d_debug::trace; |
39 | | use std::fmt::{Display, Formatter}; |
40 | | use std::rc::Rc; |
41 | | |
42 | | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
43 | | pub enum FixedFieldType { |
44 | | Int8, |
45 | | Int16, |
46 | | Int32, |
47 | | Int64, |
48 | | UInt8, |
49 | | UInt16, |
50 | | UInt32, |
51 | | UInt64, |
52 | | Float32, |
53 | | Float64, |
54 | | Bool, |
55 | | } |
56 | | |
57 | | impl Display for FixedFieldType { |
58 | 691 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
59 | 691 | match self { |
60 | 0 | FixedFieldType::Int8 => f.write_str("Int8"), |
61 | 0 | FixedFieldType::Int16 => f.write_str("Int16"), |
62 | 0 | FixedFieldType::Int32 => f.write_str("Int32"), |
63 | 0 | FixedFieldType::Int64 => f.write_str("Int64"), |
64 | 324 | FixedFieldType::UInt8 => f.write_str("UInt8"), |
65 | 77 | FixedFieldType::UInt16 => f.write_str("UInt16"), |
66 | 170 | FixedFieldType::UInt32 => f.write_str("UInt32"), |
67 | 108 | FixedFieldType::UInt64 => f.write_str("UInt64"), |
68 | 12 | FixedFieldType::Float32 => f.write_str("Float32"), |
69 | 0 | FixedFieldType::Float64 => f.write_str("Float64"), |
70 | 0 | FixedFieldType::Bool => f.write_str("Bool"), |
71 | | } |
72 | 691 | } |
73 | | } |
74 | | |
75 | 230 | fn map_numeric( |
76 | 230 | ty: SimpleType, |
77 | 230 | signed: FixedFieldType, |
78 | 230 | unsigned: FixedFieldType, |
79 | 230 | float: FixedFieldType, |
80 | 230 | ) -> Option<FixedFieldType> { |
81 | 230 | match ty { |
82 | 28 | SimpleType::Signed => Some(signed), |
83 | 198 | SimpleType::Unsigned => Some(unsigned), |
84 | 4 | SimpleType::Float => Some(float), |
85 | 0 | _ => None, |
86 | | } |
87 | 230 | } |
88 | | |
89 | | impl FixedFieldType { |
90 | 198 | pub fn get_byte_size(&self) -> usize { |
91 | 198 | match self { |
92 | 0 | FixedFieldType::Int8 => 1, |
93 | 0 | FixedFieldType::Int16 => 2, |
94 | 0 | FixedFieldType::Int32 => 4, |
95 | 0 | FixedFieldType::Int64 => 8, |
96 | 90 | FixedFieldType::UInt8 => 1, |
97 | 24 | FixedFieldType::UInt16 => 2, |
98 | 48 | FixedFieldType::UInt32 => 4, |
99 | 36 | FixedFieldType::UInt64 => 8, |
100 | 0 | FixedFieldType::Float32 => 4, |
101 | 0 | FixedFieldType::Float64 => 8, |
102 | 0 | FixedFieldType::Bool => 1, |
103 | | } |
104 | 198 | } |
105 | | |
106 | 6 | pub fn from_min_max_value(min_value: isize, max_value: isize) -> Result<Self, Error> { |
107 | 6 | match min_value < 0 { |
108 | | true => { |
109 | 2 | let bit_size = if max_value > i32::MAX as isize || min_value < i32::MIN as isize { Branch (109:35): [True: 0, False: 2]
Branch (109:68): [True: 0, False: 2]
Branch (109:35): [Folded - Ignored]
Branch (109:68): [Folded - Ignored]
|
110 | 0 | 64 |
111 | 2 | } else if max_value > i16::MAX as isize || min_value < i16::MIN as isize { Branch (111:27): [True: 0, False: 2]
Branch (111:60): [True: 0, False: 2]
Branch (111:27): [Folded - Ignored]
Branch (111:60): [Folded - Ignored]
|
112 | 0 | 32 |
113 | 2 | } else if max_value > i8::MAX as isize || min_value < i8::MIN as isize { Branch (113:27): [True: 0, False: 2]
Branch (113:59): [True: 0, False: 2]
Branch (113:27): [Folded - Ignored]
Branch (113:59): [Folded - Ignored]
|
114 | 0 | 16 |
115 | | } else { |
116 | 2 | 8 |
117 | | }; |
118 | 2 | Self::from_model(StructFieldRaw::Signed { bits: bit_size }) |
119 | | } |
120 | | false => { |
121 | 4 | let bit_size = if max_value > u32::MAX as isize { Branch (121:35): [True: 0, False: 4]
Branch (121:35): [Folded - Ignored]
|
122 | 0 | 64 |
123 | 4 | } else if max_value > u16::MAX as isize { Branch (123:27): [True: 0, False: 4]
Branch (123:27): [Folded - Ignored]
|
124 | 0 | 32 |
125 | 4 | } else if max_value > u8::MAX as isize { Branch (125:27): [True: 0, False: 4]
Branch (125:27): [Folded - Ignored]
|
126 | 0 | 16 |
127 | | } else { |
128 | 4 | 8 |
129 | | }; |
130 | 4 | Self::from_model(StructFieldRaw::Unsigned { bits: bit_size }) |
131 | | } |
132 | | } |
133 | 6 | } |
134 | | |
135 | 25 | pub fn from_max_value(max_value: usize) -> Result<Self, Error> { |
136 | 25 | let bit_size = if max_value > u32::MAX as usize { Branch (136:27): [True: 0, False: 25]
Branch (136:27): [Folded - Ignored]
|
137 | 0 | 64 |
138 | 25 | } else if max_value > u16::MAX as usize { Branch (138:19): [True: 4, False: 21]
Branch (138:19): [Folded - Ignored]
|
139 | 4 | 32 |
140 | 21 | } else if max_value > u8::MAX as usize { Branch (140:19): [True: 2, False: 19]
Branch (140:19): [Folded - Ignored]
|
141 | 2 | 16 |
142 | | } else { |
143 | 19 | 8 |
144 | | }; |
145 | 25 | Self::from_model(StructFieldRaw::Unsigned { bits: bit_size }) |
146 | 25 | } |
147 | | |
148 | 253 | pub fn from_model(ty1: StructFieldRaw) -> Result<Self, Error> { |
149 | 253 | let motherfuckingrust = ty1.clone(); |
150 | 253 | let ty = ty1.get_simple_type(); |
151 | 253 | let bit_size = ty1.get_bit_size(); |
152 | 253 | if ty == SimpleType::Boolean { Branch (152:12): [True: 12, False: 241]
Branch (152:12): [Folded - Ignored]
|
153 | 12 | Ok(Self::Bool) |
154 | 241 | } else if ty == SimpleType::Float && bit_size == 3214 { Branch (154:19): [True: 14, False: 227]
Branch (154:46): [True: 6, False: 8]
Branch (154:19): [Folded - Ignored]
Branch (154:46): [Folded - Ignored]
|
155 | 6 | Ok(Self::Float32) |
156 | 235 | } else if ty == SimpleType::Float && bit_size == 648 { Branch (156:19): [True: 8, False: 227]
Branch (156:46): [True: 4, False: 4]
Branch (156:19): [Folded - Ignored]
Branch (156:46): [Folded - Ignored]
|
157 | 4 | Ok(Self::Float64) |
158 | 231 | } else if bit_size > 32 && bit_size <= 6430 { Branch (158:19): [True: 30, False: 201]
Branch (158:36): [True: 30, False: 0]
Branch (158:19): [Folded - Ignored]
Branch (158:36): [Folded - Ignored]
|
159 | 30 | map_numeric(ty, Self::Int64, Self::UInt64, Self::Float64).ok_or(Error::UnsupportedType(motherfuckingrust)) |
160 | 201 | } else if bit_size > 16 && bit_size <= 3250 { Branch (160:19): [True: 50, False: 151]
Branch (160:36): [True: 50, False: 0]
Branch (160:19): [Folded - Ignored]
Branch (160:36): [Folded - Ignored]
|
161 | 50 | map_numeric(ty, Self::Int32, Self::UInt32, Self::Float64).ok_or(Error::UnsupportedType(motherfuckingrust)) |
162 | 151 | } else if bit_size > 8 && bit_size <= 1624 { Branch (162:19): [True: 24, False: 127]
Branch (162:35): [True: 24, False: 0]
Branch (162:19): [Folded - Ignored]
Branch (162:35): [Folded - Ignored]
|
163 | 24 | map_numeric(ty, Self::Int16, Self::UInt16, Self::Float32).ok_or(Error::UnsupportedType(motherfuckingrust)) |
164 | 127 | } else if bit_size > 0 && bit_size <= 8126 { Branch (164:19): [True: 126, False: 1]
Branch (164:35): [True: 126, False: 0]
Branch (164:19): [Folded - Ignored]
Branch (164:35): [Folded - Ignored]
|
165 | 126 | map_numeric(ty, Self::Int8, Self::UInt8, Self::Float32).ok_or(Error::UnsupportedType(motherfuckingrust)) |
166 | | } else { |
167 | 1 | Err(Error::UnsupportedBitSize(bit_size)) |
168 | | } |
169 | 253 | } |
170 | | } |
171 | | |
172 | | #[derive(Clone, Debug)] |
173 | | pub struct Location { |
174 | | pub byte_offset: usize, |
175 | | pub bit_offset: usize, |
176 | | pub byte_size: usize, |
177 | | pub bit_size: usize, |
178 | | } |
179 | | |
180 | | impl Display for Location { |
181 | 702 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
182 | 702 | write!( |
183 | 702 | f, |
184 | 702 | "bytes {}..{}, bits {}..{}", |
185 | 702 | self.byte_offset, |
186 | 702 | self.byte_offset + self.byte_size, |
187 | 702 | self.bit_offset, |
188 | 702 | self.bit_offset + self.bit_size |
189 | 702 | ) |
190 | 702 | } |
191 | | } |
192 | | |
193 | | impl Location { |
194 | 123 | fn from_model(bit_size: usize, bit_offset: usize) -> Self { |
195 | 123 | let byte_offset = bit_offset / 8; |
196 | 123 | Self { |
197 | 123 | byte_offset, |
198 | 123 | bit_offset: bit_offset - byte_offset * 8, |
199 | 123 | bit_size, |
200 | 123 | byte_size: if bit_size % 8 != 0 { Branch (200:27): [True: 32, False: 91]
Branch (200:27): [Folded - Ignored]
|
201 | 32 | (bit_size / 8) + 1 |
202 | | } else { |
203 | 91 | bit_size / 8 |
204 | | }, |
205 | | } |
206 | 123 | } |
207 | | } |
208 | | |
209 | | #[derive(Clone, Debug)] |
210 | | pub enum FieldRaw { |
211 | | /// Apply a raw C-like cast (used for unsigned > signed and unsigned > float of same bit size). |
212 | | Transmute, |
213 | | |
214 | | /// Apply a unsigned > signed cast on a non T-aligned value, |
215 | | /// the maximum positive value is passed in. |
216 | | SignedCast(usize), |
217 | | |
218 | | /// Don't do anything special, just return the raw value. |
219 | | None, |
220 | | } |
221 | | |
222 | | impl FieldRaw { |
223 | 13 | pub fn is_none(&self) -> bool { |
224 | 13 | matches!0 (self, Self::None) |
225 | 13 | } |
226 | | |
227 | 113 | fn from_model(ty: SimpleType, bit_size: usize) -> FieldRaw { |
228 | 113 | if ty == SimpleType::Float && bit_size != 3214 && bit_size != 648 { Branch (228:12): [True: 14, False: 99]
Branch (228:39): [True: 8, False: 6]
Branch (228:57): [True: 4, False: 4]
Branch (228:12): [Folded - Ignored]
Branch (228:39): [Folded - Ignored]
Branch (228:57): [Folded - Ignored]
|
229 | 4 | return FieldRaw::None; |
230 | 109 | } |
231 | 109 | if ty == SimpleType::Signed && bit_size != 826 && bit_size != 1622 && bit_size != 3218 && bit_size != 6412 { Branch (231:12): [True: 26, False: 83]
Branch (231:40): [True: 22, False: 4]
Branch (231:57): [True: 18, False: 4]
Branch (231:75): [True: 12, False: 6]
Branch (231:93): [True: 10, False: 2]
Branch (231:12): [Folded - Ignored]
Branch (231:40): [Folded - Ignored]
Branch (231:57): [Folded - Ignored]
Branch (231:75): [Folded - Ignored]
Branch (231:93): [Folded - Ignored]
|
232 | 10 | let max_value = 1 << (bit_size - 1); |
233 | 10 | FieldRaw::SignedCast(max_value - 1) |
234 | 99 | } else if ty == SimpleType::Unsigned { Branch (234:19): [True: 61, False: 38]
Branch (234:19): [Folded - Ignored]
|
235 | 61 | FieldRaw::None |
236 | | } else { |
237 | 38 | FieldRaw::Transmute |
238 | | } |
239 | 113 | } |
240 | | } |
241 | | |
242 | | #[derive(Clone, Debug)] |
243 | | pub enum FieldView { |
244 | | /// Apply a float view based on an affine transformation function. |
245 | | Float { a: f64, b: f64, a_inv: f64, b_inv: f64 }, |
246 | | |
247 | | /// Apply an enum view. |
248 | | Enum(Rc<Enum>), |
249 | | |
250 | | /// Don't do anything special, just return the raw value. |
251 | | None, |
252 | | } |
253 | | |
254 | | impl FieldView { |
255 | 117 | fn from_model( |
256 | 117 | proto: &Protocol, |
257 | 117 | ty: SimpleType, |
258 | 117 | bit_size: usize, |
259 | 117 | value: Option<StructFieldView>, |
260 | 117 | ) -> Result<Self, Error> { |
261 | 13 | match value { |
262 | 7 | Some(StructFieldView::Enum { name }) => { |
263 | 7 | if ty != SimpleType::Unsigned && ty != SimpleType::Signed3 { Branch (263:20): [True: 3, False: 4]
Branch (263:50): [True: 1, False: 2]
Branch (263:20): [Folded - Ignored]
Branch (263:50): [Folded - Ignored]
|
264 | 1 | return Err(Error::UnsupportedViewType(ty)); |
265 | 6 | } |
266 | 6 | let r = proto.enums.get(&name).ok_or(Error::UndefinedReference(name))?0 ; |
267 | 6 | Ok(FieldView::Enum(r.clone())) |
268 | | } |
269 | 3 | Some(StructFieldView::FloatRange { min, max }) => { |
270 | 3 | if ty != SimpleType::Float { Branch (270:20): [True: 1, False: 2]
Branch (270:20): [Folded - Ignored]
|
271 | 1 | return Err(Error::UnsupportedViewType(ty)); |
272 | 2 | } |
273 | 2 | let raw_max: usize = (1 << bit_size) - 1; |
274 | 2 | let a = max / (raw_max as f64); |
275 | 2 | let b = min; |
276 | 2 | let a_inv = 1.0 / a; |
277 | 2 | let b_inv = -b; |
278 | 2 | Ok(FieldView::Float { a, b, a_inv, b_inv }) |
279 | | } |
280 | 3 | Some(StructFieldView::FloatMultiplier { multiplier }) => { |
281 | 3 | if ty != SimpleType::Float { Branch (281:20): [True: 1, False: 2]
Branch (281:20): [Folded - Ignored]
|
282 | 1 | return Err(Error::UnsupportedViewType(ty)); |
283 | 2 | } |
284 | 2 | let a = multiplier; |
285 | 2 | let b = 0.0; |
286 | 2 | let a_inv = 1.0 / a; |
287 | 2 | let b_inv = 0.0; |
288 | 2 | Ok(FieldView::Float { a, b, a_inv, b_inv }) |
289 | | } |
290 | | None => { |
291 | 104 | if ty == SimpleType::Float && bit_size != 3211 && bit_size != 645 { Branch (291:20): [True: 11, False: 93]
Branch (291:47): [True: 5, False: 6]
Branch (291:65): [True: 1, False: 4]
Branch (291:20): [Folded - Ignored]
Branch (291:47): [Folded - Ignored]
Branch (291:65): [Folded - Ignored]
|
292 | 1 | return Err(Error::UnsupportedViewType(ty)); |
293 | 103 | } |
294 | 103 | Ok(FieldView::None) |
295 | | } |
296 | | } |
297 | 117 | } |
298 | | } |
299 | | |
300 | | #[derive(Clone, Debug)] |
301 | | pub struct FixedField { |
302 | | pub bits_type: FixedFieldType, |
303 | | pub raw_type: FixedFieldType, |
304 | | pub view_type: FixedFieldType, |
305 | | pub raw: FieldRaw, |
306 | | pub view: FieldView, |
307 | | pub endianness: Endianness, |
308 | | } |
309 | | |
310 | | impl Display for FixedField { |
311 | 594 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
312 | 594 | write!(f, "{}, {} endian", self.bits_type, self.endianness) |
313 | 594 | } |
314 | | } |
315 | | |
316 | | #[derive(Clone, Debug)] |
317 | | pub struct FixedArrayField { |
318 | | pub ty: FixedFieldType, |
319 | | pub array_len: usize, |
320 | | pub endianness: Endianness, |
321 | | pub item_bit_size: usize, |
322 | | } |
323 | | |
324 | | impl Display for FixedArrayField { |
325 | 36 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
326 | 36 | write!(f, "{}[{}], {} endian", self.ty, self.array_len, self.endianness) |
327 | 36 | } |
328 | | } |
329 | | |
330 | | #[derive(Clone, Debug)] |
331 | | pub enum FieldType { |
332 | | Fixed(FixedField), |
333 | | Array(FixedArrayField), |
334 | | Struct(Rc<Structure>), |
335 | | } |
336 | | |
337 | | impl Display for FieldType { |
338 | 702 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
339 | 702 | match self { |
340 | 594 | FieldType::Fixed(v) => v.fmt(f), |
341 | 36 | FieldType::Array(v) => v.fmt(f), |
342 | 72 | FieldType::Struct(v) => f.write_str(v.name()), |
343 | | } |
344 | 702 | } |
345 | | } |
346 | | |
347 | | impl FieldType { |
348 | 268 | pub fn as_fixed(&self) -> Option<&FixedField> { |
349 | 268 | match self { |
350 | 268 | FieldType::Fixed(v) => Some(v), |
351 | 0 | _ => None, |
352 | | } |
353 | 268 | } |
354 | | } |
355 | | |
356 | | #[derive(Clone, Debug)] |
357 | | pub struct Field { |
358 | | pub name: String, |
359 | | pub loc: Location, |
360 | | pub description: Option<Description>, |
361 | | pub ty: FieldType, |
362 | | } |
363 | | |
364 | | impl Display for Field { |
365 | 702 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
366 | 702 | write!(f, "{}: {} ({})", self.name, self.ty, self.loc) |
367 | 702 | } |
368 | | } |
369 | | |
370 | | impl Field { |
371 | 131 | fn from_model( |
372 | 131 | proto: &Protocol, |
373 | 131 | fields: &[Field], |
374 | 131 | mut last_bit_offset: usize, |
375 | 131 | value: crate::model::structure::StructField, |
376 | 131 | ) -> Result<(Self, usize), Error> { |
377 | 131 | if (value.raw.is_none() && value.item_type.is_none()13 ) || (value.raw.is_some() && value.item_type.is_some()118 ) { Branch (377:13): [True: 13, False: 118]
Branch (377:36): [True: 0, False: 13]
Branch (377:67): [True: 118, False: 13]
Branch (377:90): [True: 0, False: 118]
Branch (377:13): [Folded - Ignored]
Branch (377:36): [Folded - Ignored]
Branch (377:67): [Folded - Ignored]
Branch (377:90): [Folded - Ignored]
|
378 | 0 | return Err(Error::BadFieldType); |
379 | 131 | } |
380 | 131 | let (ty, bit_size123 ) = if let Some(info118 ) = value.raw { Branch (380:37): [True: 118, False: 13]
Branch (380:37): [Folded - Ignored]
|
381 | 118 | let array_len = value.array_len.unwrap_or(1); |
382 | 118 | if array_len == 0 { Branch (382:16): [True: 1, False: 117]
Branch (382:16): [Folded - Ignored]
|
383 | 1 | return Err(Error::ZeroArray); |
384 | 117 | } |
385 | 117 | let mut bit_size = info.get_bit_size(); |
386 | 117 | let view113 = FieldView::from_model(proto, info.get_simple_type(), bit_size, value.view)?4 ; |
387 | 113 | let raw = FieldRaw::from_model(info.get_simple_type(), bit_size); |
388 | 113 | bit_size *= array_len; |
389 | 113 | let ty112 = FixedFieldType::from_model(info)?1 ; |
390 | 112 | if array_len > 1 { Branch (390:16): [True: 7, False: 105]
Branch (390:16): [Folded - Ignored]
|
391 | 7 | if (bit_size / array_len) % 8 != 0 { Branch (391:20): [True: 1, False: 6]
Branch (391:20): [Folded - Ignored]
|
392 | 1 | return Err(Error::UnalignedArrayCodec); |
393 | 6 | } |
394 | 6 | ( |
395 | 6 | FieldType::Array(FixedArrayField { |
396 | 6 | endianness: proto.endianness, |
397 | 6 | array_len, |
398 | 6 | ty, |
399 | 6 | item_bit_size: bit_size / array_len, |
400 | 6 | }), |
401 | 6 | bit_size, |
402 | 6 | ) |
403 | | } else { |
404 | 105 | let bits_type = FixedFieldType::from_model(StructFieldRaw::Unsigned { bits: bit_size })?0 ; |
405 | 105 | let raw_type = match (bit_size, ty) { |
406 | 4 | (32, FixedFieldType::Float32) => FixedFieldType::Float32, |
407 | 4 | (64, FixedFieldType::Float64) => FixedFieldType::Float64, |
408 | 2 | (_, FixedFieldType::Float32) => bits_type, |
409 | 2 | (_, FixedFieldType::Float64) => bits_type, |
410 | 93 | _ => ty, |
411 | | }; |
412 | 105 | ( |
413 | 105 | FieldType::Fixed(FixedField { |
414 | 105 | endianness: proto.endianness, |
415 | 105 | bits_type, |
416 | 105 | raw_type, |
417 | 105 | view_type: ty, |
418 | 105 | view, |
419 | 105 | raw, |
420 | 105 | }), |
421 | 105 | bit_size, |
422 | 105 | ) |
423 | | } |
424 | | } else { |
425 | 13 | let item_type = unsafe { value.item_type.unwrap_unchecked() }; |
426 | 13 | let r = try2!12 (proto.structs.get(&item_type) => Error::UndefinedReference(item_type)1 ); |
427 | 12 | trace!("Solved reference {} => {:?}", item_type, r); |
428 | 12 | (FieldType::Struct(r.clone()), r.bit_size) |
429 | | }; |
430 | 123 | let loc = match value.offset { |
431 | | None => { |
432 | 119 | let loc = Location::from_model(bit_size, last_bit_offset); |
433 | 119 | last_bit_offset += bit_size; |
434 | 119 | loc |
435 | | } |
436 | 4 | Some(v) => match v.relative_to { |
437 | | None => { |
438 | 2 | let start_bits = v.bits.unwrap_or(0); |
439 | 2 | let end_bits = start_bits + bit_size; |
440 | 2 | if end_bits > last_bit_offset { Branch (440:24): [True: 0, False: 2]
Branch (440:24): [Folded - Ignored]
|
441 | 0 | last_bit_offset = end_bits; |
442 | 2 | } |
443 | 2 | Location::from_model(bit_size, start_bits) |
444 | | } |
445 | 2 | Some(name) => { |
446 | 12 | let field2 = fields.iter().find(2 |v| v.name == name).ok_or(Error::UndefinedReference(name))2 ?0 ; |
447 | 2 | let start_bits = field.loc.bit_offset + v.bits.unwrap_or(0); |
448 | 2 | let end_bits = start_bits + bit_size; |
449 | 2 | if end_bits > last_bit_offset { Branch (449:24): [True: 0, False: 2]
Branch (449:24): [Folded - Ignored]
|
450 | 0 | last_bit_offset = end_bits; |
451 | 2 | } |
452 | 2 | Location::from_model(bit_size, start_bits) |
453 | | } |
454 | | }, |
455 | | }; |
456 | 123 | Ok(( |
457 | 123 | Self { |
458 | 123 | name: value.name, |
459 | 123 | ty, |
460 | 123 | loc, |
461 | 123 | description: value.description, |
462 | 123 | }, |
463 | 123 | last_bit_offset, |
464 | 123 | )) |
465 | 131 | } |
466 | | } |
467 | | |
468 | | #[derive(Clone, Debug)] |
469 | | pub struct Structure { |
470 | | pub name: String, |
471 | | pub description: Option<Description>, |
472 | | pub fields: Vec<Field>, |
473 | | pub byte_size: usize, |
474 | | pub bit_size: usize, |
475 | | used_in_header: Cell<bool> |
476 | | } |
477 | | |
478 | | impl Structure { |
479 | 8 | pub fn set_used_in_header(&self) { |
480 | 8 | self.used_in_header.set(true); |
481 | 8 | } |
482 | | |
483 | 118 | pub fn is_used_in_header(&self) -> bool { |
484 | 118 | self.used_in_header.get() |
485 | 118 | } |
486 | | |
487 | 74 | pub fn from_model(proto: &Protocol, value: crate::model::structure::Structure) -> Result<Structure, Error> { |
488 | 74 | let mut fields = Vec::with_capacity(value.fields.len()); |
489 | 74 | let mut last_bit_offset = 0; |
490 | 197 | for field131 in value.fields { |
491 | 131 | let (field, new_offset123 ) = Field::from_model(proto, &fields, last_bit_offset, field)?8 ; |
492 | 123 | fields.push(field); |
493 | 123 | last_bit_offset = new_offset; |
494 | | } |
495 | 66 | let s = Structure { |
496 | 66 | name: value.name, |
497 | 66 | description: value.description, |
498 | 66 | fields, |
499 | 66 | bit_size: last_bit_offset, |
500 | 66 | byte_size: if last_bit_offset % 8 != 0 { Branch (500:27): [True: 0, False: 66]
Branch (500:27): [Folded - Ignored]
|
501 | 0 | (last_bit_offset / 8) + 1 |
502 | | } else { |
503 | 66 | last_bit_offset / 8 |
504 | | }, |
505 | 66 | used_in_header: Cell::new(false) |
506 | 66 | }; |
507 | 66 | if s.bit_size == 0 { Branch (507:12): [True: 1, False: 65]
Branch (507:12): [Folded - Ignored]
|
508 | 1 | return Err(Error::ZeroStruct); |
509 | 65 | } |
510 | 65 | Ok(s) |
511 | 74 | } |
512 | | } |
513 | | |
514 | | name_index!(Structure => name); |